Skip to content

feat: tri-mode BLE dongle - #1028

Open
HaoboGu wants to merge 3 commits into
feat/dongle-groundworkfrom
feat/dongle-core
Open

feat: tri-mode BLE dongle#1028
HaoboGu wants to merge 3 commits into
feat/dongle-groundworkfrom
feat/dongle-core

Conversation

@HaoboGu

@HaoboGu HaoboGu commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

The dongle itself: a BLE central that pairs with RMK keyboards and relays them to the host over USB. HID reports are merged across links (modifiers OR'd, keycodes unioned), and the Rynk config session is routed — 0x09xx dongle commands answered locally, everything else passed through to the selected keyboard over its rynk GATT service, with topic pushes forwarded back.

  • rmk::dongle: slot table with bond persistence and Lamport-recency eviction; per-link state machine (claim → connect → secure → handshake → serve) with LESC Just Works pairing gated by an RSSI-selected 30 s pairing window; HID merge; the USB frame router.
  • Dongle::new(controller, address, slots) owns its stack, sized by DONGLE_LINKS_NUM; slots come from new_storage_for_dongle.
  • UsbTransport::with_dongle_router attaches the router. The dongle feature is orthogonal to rynk/vial: one crate can build keyboard and dongle binaries side by side (CI covers the union feature set).
  • examples/use_rust/nrf_dongle: tri-board reference — nRF54LM20A dongle, nRF52833 split central, nRF54L15 split peripheral.

Hardware-tested end to end on the tri-board rig: pairing via SwitchToDongle, typing through the split (both halves), config pass-through over USB, and bonded directed reconnect after a dongle power-cycle. Design doc included (zh + en).

Stack 4/4 — depends on #1027.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 397.6 KiB 397.6 KiB +0.00% ⬆️ +40 0 0
use_config/nrf52840_ble 439.6 KiB 439.5 KiB -0.02% ⬇️ -128 0 +8
use_config/nrf52840_ble_split (central) 500.8 KiB 501.5 KiB +0.14% ⬆️ +736 0 +8
use_config/nrf52840_ble_split (peripheral) 318.8 KiB 318.8 KiB +0.00% 0 0 0
use_config/pi_pico_w_ble 672.7 KiB 673.0 KiB +0.04% ⬆️ +288 0 +8
use_config/rp2040 146.3 KiB 146.3 KiB +0.01% ⬆️ +16 0 +8
use_config/rp2040_split (central) 159.9 KiB 160.1 KiB +0.09% ⬆️ +152 0 +8
use_config/rp2040_split (peripheral) 27.9 KiB 27.9 KiB +0.00% 0 0 0
use_config/stm32f1 62.6 KiB 62.6 KiB +0.04% ⬆️ +28 0 0
use_config/stm32h7 100.4 KiB 100.5 KiB +0.05% ⬆️ +52 0 +8
use_rust/nrf52832_ble 385.2 KiB 385.5 KiB +0.09% ⬆️ +368 0 0
use_rust/nrf52840_ble 435.2 KiB 434.9 KiB -0.07% ⬇️ -340 0 +8
use_rust/nrf52840_ble_split (central) 504.3 KiB 504.9 KiB +0.11% ⬆️ +600 0 +8
use_rust/nrf52840_ble_split (peripheral) 316.4 KiB 316.4 KiB +0.00% 0 0 0
use_rust/pi_pico_w_ble 672.1 KiB 672.1 KiB +0.00% ⬆️ +44 0 +8
use_rust/rp2040 145.6 KiB 145.9 KiB +0.20% ⬆️ +292 0 +8
use_rust/rp2040_split (central) 158.4 KiB 158.7 KiB +0.15% ⬆️ +248 0 +8
use_rust/rp2040_split (peripheral) 28.2 KiB 28.2 KiB +0.00% 0 0 0
use_rust/stm32f1 61.9 KiB 61.9 KiB +0.04% ⬆️ +28 0 0
use_rust/stm32h7 119.7 KiB 119.7 KiB +0.05% ⬆️ +60 0 +8
use_config/nrf52832_ble — 397.6 KiB → 397.6 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 364912	   8620	  33624	 407156	  63674	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 364872	   8620	  33624	 407116	  6364c	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0% +1.32Ki  [ = ]       0    .debug_str
  +0.1%    +993  [ = ]       0    .debug_info
  +0.0%    +102  [ = ]       0    .strtab
  +0.9%     +70  [ = ]       0    .debug_abbrev
  +0.0%     +40  +0.0%     +40    .text
 -14.8%      -9  [ = ]       0    [Unmapped]
  -0.0%     -34  [ = ]       0    .debug_line
  -0.1%    -112  [ = ]       0    .debug_ranges
  -0.2% -1.50Ki  [ = ]       0    .debug_loc
  +0.0%    +864  +0.0%     +40    TOTAL
use_config/nrf52840_ble — 439.6 KiB → 439.5 KiB (-0.02% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397776	   8628	  43672	 450076	  6de1c	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397904	   8628	  43664	 450196	  6de94	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.12Ki  [ = ]       0    .debug_str
  +0.1% +1.79Ki  [ = ]       0    .debug_info
  +0.2% +1.18Ki  [ = ]       0    .debug_loc
  +0.0%    +137  [ = ]       0    .strtab
  +0.0%     +82  [ = ]       0    .debug_line
  +0.5%     +39  [ = ]       0    .debug_abbrev
  [ = ]       0  +0.0%      +8    .bss
  -6.5%      -3  [ = ]       0    [Unmapped]
  -0.0%     -16  [ = ]       0    .symtab
  -0.0%     -24  [ = ]       0    .debug_aranges
  -0.1%     -36  [ = ]       0    .debug_frame
  -0.0%     -56  [ = ]       0    .debug_ranges
  -0.0%    -128  -0.0%    -128    .text
  +0.1% +7.08Ki  -0.0%    -120    TOTAL
use_config/nrf52840_ble_split (central) — 500.8 KiB → 501.5 KiB (+0.14% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 455992	   8684	  48864	 513540	  7d604	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 455256	   8684	  48856	 512796	  7d31c	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.49Ki  [ = ]       0    .debug_str
  +0.1% +1.53Ki  [ = ]       0    .debug_info
  +0.2%    +736  +0.2%    +736    .text
  +0.1%    +325  [ = ]       0    .strtab
  +0.1%    +320  [ = ]       0    .debug_ranges
  +0.1%    +176  [ = ]       0    .symtab
  +0.0%    +157  [ = ]       0    .debug_line
  +0.1%     +76  [ = ]       0    .debug_frame
  +0.1%     +32  [ = ]       0    .debug_aranges
  [ = ]       0  +0.0%      +8    .bss
  -8.2%      -4  [ = ]       0    [Unmapped]
  -0.0%    -298  [ = ]       0    .debug_loc
  +0.1% +7.51Ki  +0.1%    +744    TOTAL
use_config/nrf52840_ble_split (peripheral) — 318.8 KiB → 318.8 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 292804	   8500	  25184	 326488	  4fb58	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 292804	   8500	  25184	 326488	  4fb58	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +13  [ = ]       0    .debug_info
  +0.0%     +12  [ = ]       0    .debug_str
  +0.0%     +11  [ = ]       0    .strtab
  +0.0%      +8  [ = ]       0    .debug_line
  +3.6%      +2  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  +0.0%     +36  [ = ]       0    TOTAL
use_config/pi_pico_w_ble — 672.7 KiB → 673.0 KiB (+0.04% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 635392	      0	  53712	 689104	  a83d0	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 635104	      0	  53704	 688808	  a82a8	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.52Ki  [ = ]       0    .debug_str
  +0.1% +1.95Ki  [ = ]       0    .debug_info
  +0.0%    +405  [ = ]       0    .debug_loc
  +0.1%    +345  [ = ]       0    .debug_line
  +0.1%    +288  +0.1%    +288    .text
  +0.1%    +269  [ = ]       0    .strtab
  +0.2%    +144  [ = ]       0    .symtab
  +0.4%     +39  [ = ]       0    .debug_abbrev
  +0.1%     +28  [ = ]       0    .debug_frame
  [ = ]       0  +0.0%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
  +4.3%      +2  [ = ]       0    [Unmapped]
  -0.1%    -152  [ = ]       0    .debug_ranges
  +0.1% +7.81Ki  +0.0%    +296    TOTAL
use_config/rp2040 — 146.3 KiB → 146.3 KiB (+0.01% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135896	      0	  13916	 149812	  24934	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135880	      0	  13908	 149788	  2491c	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.17Ki  [ = ]       0    .debug_str
  +0.9% +2.70Ki  [ = ]       0    .debug_loc
  +0.1%    +765  [ = ]       0    .debug_info
  +0.4%    +344  [ = ]       0    .debug_ranges
  +0.1%    +163  [ = ]       0    .strtab
  +0.1%     +96  [ = ]       0    .debug_line
  +0.2%     +28  [ = ]       0    .debug_frame
   +46%     +18  [ = ]       0    [Unmapped]
  +0.0%     +16  +0.0%     +16    .text
  [ = ]       0  +0.1%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
  -0.0%     -16  [ = ]       0    .symtab
  +0.2% +7.25Ki  +0.0%     +24    TOTAL
use_config/rp2040_split (central) — 159.9 KiB → 160.1 KiB (+0.09% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 149060	      0	  14868	 163928	  28058	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 148908	      0	  14860	 163768	  27fb8	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.9% +3.11Ki  [ = ]       0    .debug_loc
  +0.1% +2.82Ki  [ = ]       0    .debug_str
  +0.1%    +883  [ = ]       0    .debug_info
  +0.4%    +360  [ = ]       0    .debug_ranges
  +0.1%    +152  +0.1%    +152    .text
  +0.1%    +142  [ = ]       0    .strtab
  +0.2%     +80  [ = ]       0    .symtab
  +0.1%     +28  [ = ]       0    .debug_frame
  [ = ]       0  +0.1%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
   +20%      +7  [ = ]       0    [Unmapped]
  +0.0%      +3  [ = ]       0    .debug_line
  +0.2% +7.55Ki  +0.1%    +160    TOTAL
use_config/rp2040_split (peripheral) — 27.9 KiB → 27.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25696	     60	   2804	  28560	   6f90	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25696	     60	   2804	  28560	   6f90	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +4  [ = ]       0    .debug_line
  +3.9%      +2  [ = ]       0    [Unmapped]
  -0.0%      -3  [ = ]       0    .debug_str
  -0.0%      -3  [ = ]       0    .strtab
  [ = ]       0  [ = ]       0    TOTAL
use_config/stm32f1 — 62.6 KiB → 62.6 KiB (+0.04% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57772	     28	   6336	  64136	   fa88	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57744	     28	   6336	  64108	   fa6c	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +1.94Ki  [ = ]       0    .debug_str
  +0.7%    +925  [ = ]       0    .debug_loc
  +0.2%    +880  [ = ]       0    .debug_info
  +0.1%     +66  [ = ]       0    .debug_line
  +0.1%     +48  [ = ]       0    .debug_ranges
  +0.0%     +28  +0.0%     +28    .text
  -0.4%     -24  [ = ]       0    .debug_aranges
 -39.7%     -27  [ = ]       0    [Unmapped]
  -0.4%     -48  [ = ]       0    .debug_frame
  -0.3%     -64  [ = ]       0    .symtab
  -0.2%     -78  [ = ]       0    .strtab
  +0.2% +3.60Ki  +0.0%     +28    TOTAL
use_config/stm32h7 — 100.4 KiB → 100.5 KiB (+0.05% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  94492	    264	   8136	 102892	  191ec	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  94440	    264	   8128	 102832	  191b0	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.69Ki  [ = ]       0    .debug_str
  +0.8% +1.35Ki  [ = ]       0    .debug_loc
  +0.1%    +812  [ = ]       0    .debug_info
  +0.8%    +520  [ = ]       0    .debug_ranges
  +0.3%    +345  [ = ]       0    .debug_line
  +0.5%    +306  [ = ]       0    .strtab
  +0.1%     +52  +0.1%     +52    .text
  +0.2%     +48  [ = ]       0    .symtab
  +0.2%     +28  [ = ]       0    .debug_frame
  [ = ]       0  +0.1%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
 -25.8%     -16  [ = ]       0    [Unmapped]
  +0.2% +7.10Ki  +0.1%     +60    TOTAL
use_rust/nrf52832_ble — 385.2 KiB → 385.5 KiB (+0.09% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 352596	   8620	  33560	 394776	  60618	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 352228	   8620	  33560	 394408	  604a8	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0% +1.38Ki  [ = ]       0    .debug_str
  +0.1% +1.21Ki  [ = ]       0    .debug_info
  +0.1%    +381  [ = ]       0    .debug_line
  +0.1%    +368  +0.1%    +368    .text
  +0.1%    +168  [ = ]       0    .debug_ranges
  +0.0%     +25  [ = ]       0    .strtab
  +0.1%     +12  [ = ]       0    .debug_abbrev
 -27.7%     -18  [ = ]       0    [Unmapped]
  -0.1%     -24  [ = ]       0    .debug_aranges
  -0.1%     -48  [ = ]       0    .debug_frame
  -0.1%     -96  [ = ]       0    .symtab
  -0.2% -1.36Ki  [ = ]       0    .debug_loc
  +0.0% +1.98Ki  +0.1%    +368    TOTAL
use_rust/nrf52840_ble — 435.2 KiB → 434.9 KiB (-0.07% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 395800	   8628	  40912	 445340	  6cb9c	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 396140	   8628	  40904	 445672	  6cce8	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.79Ki  [ = ]       0    .debug_str
  +0.1% +2.01Ki  [ = ]       0    .debug_info
  +0.2% +1.55Ki  [ = ]       0    .debug_loc
  +0.1%    +465  [ = ]       0    .debug_line
  +0.1%    +176  [ = ]       0    .debug_ranges
   +33%     +16  [ = ]       0    [Unmapped]
  [ = ]       0  +0.0%      +8    .bss
  -0.0%     -37  [ = ]       0    .strtab
  -0.2%     -80  [ = ]       0    .debug_aranges
  -0.3%    -148  [ = ]       0    .debug_frame
  -0.1%    -340  -0.1%    -340    .text
  -0.3%    -400  [ = ]       0    .symtab
  +0.1% +7.01Ki  -0.1%    -332    TOTAL
use_rust/nrf52840_ble_split (central) — 504.3 KiB → 504.9 KiB (+0.11% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 457476	   8684	  50832	 516992	  7e380	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 456876	   8684	  50824	 516384	  7e120	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.26Ki  [ = ]       0    .debug_str
  +0.0%    +748  [ = ]       0    .debug_info
  +0.1%    +613  [ = ]       0    .debug_loc
  +0.1%    +600  +0.1%    +600    .text
  +0.2%    +464  [ = ]       0    .debug_ranges
  +0.1%    +442  [ = ]       0    .strtab
  +0.2%    +304  [ = ]       0    .symtab
  +0.1%    +244  [ = ]       0    .debug_line
  +0.3%    +156  [ = ]       0    .debug_frame
  +0.1%     +72  [ = ]       0    .debug_aranges
   +20%     +11  [ = ]       0    [Unmapped]
  [ = ]       0  +0.0%      +8    .bss
  +0.1% +6.83Ki  +0.1%    +608    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 316.4 KiB → 316.4 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 290540	   8500	  24952	 323992	  4f198	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 290540	   8500	  24952	 323992	  4f198	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +13  [ = ]       0    .debug_info
  +0.0%     +12  [ = ]       0    .strtab
  +0.0%     +11  [ = ]       0    .debug_str
  +0.0%      +7  [ = ]       0    .debug_line
  -2.0%      -1  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  +0.0%     +32  [ = ]       0    TOTAL
use_rust/pi_pico_w_ble — 672.1 KiB → 672.1 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 634884	      0	  53392	 688276	  a8094	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 634840	      0	  53384	 688224	  a8060	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.30Ki  [ = ]       0    .debug_str
  +0.1% +1.75Ki  [ = ]       0    .debug_info
  +0.0%    +257  [ = ]       0    .debug_loc
  +0.1%    +209  [ = ]       0    .strtab
  +0.1%     +80  [ = ]       0    .symtab
  +0.0%     +44  +0.0%     +44    .text
  +0.1%     +28  [ = ]       0    .debug_frame
  [ = ]       0  +0.0%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
 -24.1%     -14  [ = ]       0    [Unmapped]
  -0.0%     -31  [ = ]       0    .debug_line
  -0.0%     -32  [ = ]       0    .debug_ranges
  +0.1% +6.58Ki  +0.0%     +52    TOTAL
use_rust/rp2040 — 145.6 KiB → 145.9 KiB (+0.20% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135604	      0	  13756	 149360	  24770	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135312	      0	  13748	 149060	  24644	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +3.73Ki  [ = ]       0    .debug_str
  +0.6% +1.80Ki  [ = ]       0    .debug_loc
  +0.1%    +993  [ = ]       0    .debug_info
  +0.2%    +292  +0.2%    +292    .text
  +0.1%    +234  [ = ]       0    .debug_line
  +0.3%    +224  [ = ]       0    .debug_ranges
  +0.1%    +167  [ = ]       0    .strtab
  +0.1%     +48  [ = ]       0    .symtab
  +0.2%     +28  [ = ]       0    .debug_frame
  [ = ]       0  +0.1%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
  -3.2%      -2  [ = ]       0    [Unmapped]
  +0.2% +7.47Ki  +0.2%    +300    TOTAL
use_rust/rp2040_split (central) — 158.4 KiB → 158.7 KiB (+0.15% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 147856	      0	  14612	 162468	  27aa4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 147608	      0	  14604	 162212	  279a4	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +1.4% +4.93Ki  [ = ]       0    .debug_loc
  +0.2% +3.06Ki  [ = ]       0    .debug_str
  +0.1%    +884  [ = ]       0    .debug_info
  +0.8%    +272  [ = ]       0    .symtab
  +0.3%    +264  [ = ]       0    .debug_ranges
  +0.2%    +248  +0.2%    +248    .text
  +0.1%    +182  [ = ]       0    .strtab
  +0.1%     +28  [ = ]       0    .debug_frame
  +0.0%     +18  [ = ]       0    .debug_line
  [ = ]       0  +0.1%      +8    .bss
  +0.0%      +8  [ = ]       0    .debug_aranges
   +14%      +8  [ = ]       0    [Unmapped]
  +0.2% +9.85Ki  +0.2%    +256    TOTAL
use_rust/rp2040_split (peripheral) — 28.2 KiB → 28.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25796	     60	   3068	  28924	   70fc	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25796	     60	   3068	  28924	   70fc	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +4  [ = ]       0    .debug_line
  +4.2%      +2  [ = ]       0    [Unmapped]
  -0.0%      -3  [ = ]       0    .debug_str
  -0.0%      -3  [ = ]       0    .strtab
  [ = ]       0  [ = ]       0    TOTAL
use_rust/stm32f1 — 61.9 KiB → 61.9 KiB (+0.04% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57112	     28	   6272	  63412	   f7b4	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57084	     28	   6272	  63384	   f798	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +2.12Ki  [ = ]       0    .debug_str
  +0.2%    +954  [ = ]       0    .debug_info
  +0.4%    +453  [ = ]       0    .debug_loc
  +0.3%    +128  [ = ]       0    .debug_ranges
  +0.1%     +66  [ = ]       0    .debug_line
  +0.0%     +28  +0.0%     +28    .text
  +0.0%      +9  [ = ]       0    .strtab
  +7.0%      +4  [ = ]       0    [Unmapped]
  +0.2% +3.73Ki  +0.0%     +28    TOTAL
use_rust/stm32h7 — 119.7 KiB → 119.7 KiB (+0.05% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 108248	    320	  14036	 122604	  1deec	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 108188	    320	  14028	 122536	  1dea8	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +3.56Ki  [ = ]       0    .debug_str
  +0.4%    +991  [ = ]       0    .debug_loc
  +0.1%    +894  [ = ]       0    .debug_info
  +0.4%    +320  [ = ]       0    .debug_ranges
  +0.1%    +133  [ = ]       0    .strtab
  +0.1%     +60  +0.1%     +60    .text
  +0.1%     +12  [ = ]       0    .debug_frame
  [ = ]       0  +0.1%      +8    .bss
  +9.3%      +5  [ = ]       0    [Unmapped]
  -0.0%     -16  [ = ]       0    .symtab
  -0.1%     -80  [ = ]       0    .debug_line
  +0.1% +5.82Ki  +0.1%     +68    TOTAL

@HaoboGu
HaoboGu force-pushed the feat/dongle-core branch 2 times, most recently from 0667f5d to f7478fd Compare August 4, 2026 12:37
@HaoboGu
HaoboGu force-pushed the feat/dongle-core branch 2 times, most recently from 1637b06 to 9faaf4b Compare August 5, 2026 06:54
@HaoboGu
HaoboGu force-pushed the feat/dongle-core branch 2 times, most recently from 15955c2 to af7c0d3 Compare August 5, 2026 08:52
HaoboGu added 3 commits August 7, 2026 16:04
A BLE keyboard built with `rynk` can now be the peripheral half of a
tri-mode dongle link:

- a dedicated `DONGLE_PROFILE` bond slot (`NUM_BLE_PROFILE`) with its own
  `SwitchToDongle` key, so switching to the dongle never evicts a host bond;
- dongle-seeking advertising (legacy 1M, non-discoverable, carrying the Rynk
  major) and directed re-advertising to a bonded dongle;
- the `dongle_ctrl` characteristic: holding the dongle key for 5s notifies
  `DONGLE_CTRL_OPEN_PAIRING_WINDOW`, authorizing the dongle to pair another
  keyboard;
- Apple connection-parameter tuning is skipped on the dongle profile, where
  the dongle owns the parameters.
A dongle binary (`dongle` feature) relays bonded RMK keyboards to a USB
host: HID-over-GATT client toward each keyboard, Rynk GATT client toward the
configuration target, and Rynk server on USB. Keymaps and storage stay on the
keyboards; the dongle persists only its slot table (bond + name + recency).

- `rmk::dongle`: `link` (one task per concurrent link: connect, secure,
  handshake, serve), `merge` (N keyboards into one HID report set), `router`
  (self-answers `0x09xx`, passes every other frame through byte-for-byte),
  and the pairing window (power-on, or authorized by a bonded keyboard).
- Orthogonal to `rynk`/`vial`: one crate can build keyboard and dongle
  binaries side by side, each sizing its own BLE stack.
- `examples/use_rust/nrf_dongle`: dongle (nRF54LM20A) + split central
  (nRF52833) + split peripheral (nRF54L15), the three-board setup this was
  validated on.

Two constraints found on hardware and kept in comments: the keyboard's
dongle-seeking advertisement must be legacy 1M (2M ext adv desyncs a legacy
initiator), and peripheral latency must be 0 during pairing (the central's
~400ms P-256 pauses otherwise starve the link).
Adapts to the dense slot table and the folded probe, and removes the version
handshake the probe change made redundant:

- `slots_snapshot()` emits one entry per slot, `None` for unbonded, so the
  index is the slot number `SelectDongleTarget`/`ForgetDongleSlot` take.
- `GetDongleSlots` takes over the `GetDongleInfo` arm, including the gate
  that keeps `DongleSlotsChange` muted until the host has read the table —
  which now reads better, since a push is a delta of that first read.
- The version gate is gone. It killed the whole link on a Rynk major
  mismatch, but typing rides HOGP and doesn't care what config protocol the
  keyboard speaks, and the host reports a mismatch with a far better message
  once it connects through us. New pairings were never affected either way:
  the seeking advertisement carries `[0xD0, our major]`, so a mismatched
  keyboard is filtered at the scan — the gate only fired on a bonded keyboard
  whose firmware had been upgraded, exactly the case that should keep typing.
- `version_bad` goes with it. The flag patched a loop the probe itself
  created: fail → disconnect → `claim()` reselects the slot → reconnect →
  fail. No probe, no loop, no flag.
- The name now comes from the GAP Device Name (0x2A00) — the same value RMK
  publishes as `DeviceInfo::product_name`, but a standard characteristic
  rather than a Rynk payload. A failed or truncated read leaves the slot
  unnamed instead of dropping the link; that part is load-bearing, since a
  `GetDeviceInfo` that fails to decode would otherwise rebuild the same
  redial loop with no flag left to stop it.

The dongle now issues zero Rynk requests and depends only on the frozen frame
header, so payload types can evolve without a dongle firmware update. The seq
space belongs entirely to the host, retiring the "pass-through only opens
after the handshake, so no seq can collide" ordering constraint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant